package com.geeguo.ebuilder.operation.business.system.operlog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geeguo.ebuilder.core.common.dictionary.BooleanEnum;
import com.geeguo.ebuilder.core.common.model.vo.PageListVO;
import com.geeguo.ebuilder.core.common.utils.IpUtils;
import com.geeguo.ebuilder.core.common.utils.PageUtils;
import com.geeguo.ebuilder.core.common.utils.key.UUIDGenerator;
import com.geeguo.ebuilder.operation.base.core.dictionary.ClientTypeEnum;
import com.geeguo.ebuilder.operation.base.core.dictionary.LogTypeEnum;
import com.geeguo.ebuilder.operation.base.security.model.LoginUser;
import com.geeguo.ebuilder.operation.base.log.model.LogRecord;
import com.geeguo.ebuilder.operation.base.log.service.LogRecordService;
import com.geeguo.ebuilder.operation.business.system.operlog.mapper.OperLogMapper;
import com.geeguo.ebuilder.operation.business.system.operlog.model.OperLogConverter;
import com.geeguo.ebuilder.operation.business.system.operlog.model.OperLogEntity;
import com.geeguo.ebuilder.operation.business.system.operlog.model.OperLogQuery;
import com.geeguo.ebuilder.operation.business.system.operlog.model.OperLogVO;
import com.geeguo.ebuilder.operation.business.system.operlog.service.OperLogService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Service
public class OperLogServiceImpl implements OperLogService, LogRecordService {

    @Autowired
    private OperLogMapper operLogMapper;

    @Override
    public PageListVO<OperLogVO> list(OperLogQuery query) {
        LambdaQueryWrapper<OperLogEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(query.getLogType() != null, OperLogEntity::getLogType, query.getLogType());
        queryWrapper.eq(query.getClientType() != null, OperLogEntity::getClientType, query.getClientType());
        queryWrapper.orderByDesc(OperLogEntity::getCreateTime);
        IPage<OperLogEntity> page = operLogMapper.selectPage(new Page<>(query.getPageNo(), query.getPageSize()), queryWrapper);
        List<OperLogVO> operLogList = new ArrayList<>();
        if (page.getRecords() != null && !page.getRecords().isEmpty()) {
            for (OperLogEntity item : page.getRecords()) {
                operLogList.add(OperLogConverter.INSTANCE.convert2VO(item));
            }
        }
        return PageUtils.getPageListVO(page, operLogList);
    }

    @Override
    public OperLogVO get(String id) {
        OperLogEntity operLog = operLogMapper.selectById(id);
        if (operLog != null) {
            return OperLogConverter.INSTANCE.convert2VO(operLog);
        }
        return null;
    }

    @Override
    public boolean save(OperLogEntity operLog) {
        return operLogMapper.insert(operLog) > 0;
    }

    @Async
    @Override
    public CompletableFuture<Boolean> saveLoginLog(LoginUser user, HttpServletRequest request) {
        OperLogEntity operLog = new OperLogEntity();
        operLog.setId(UUIDGenerator.getId());
        operLog.setTitle("用户登录");
        operLog.setLogType(LogTypeEnum.LOGIN.getValue());
        operLog.setClientType(ClientTypeEnum.Web.getValue());
        operLog.setMethod("AuthorizationController.login()");
        operLog.setUserId(user.getUserId());
        operLog.setUsername(user.getUsername());
        operLog.setIp(IpUtils.getIpAddr(request));
        operLog.setUrl("/system/authorization/login");
        operLog.setRequestMethod("POST");
        operLog.setSuccess(BooleanEnum.True.getValue());
        operLog.setCreateTime(new Date());
        operLog.setCreateUser(user.getUserId());
        return CompletableFuture.completedFuture(save(operLog));
    }

    @Async
    @Override
    public CompletableFuture<Boolean> record(LogRecord logRecord) {
        OperLogEntity operLogEntity = OperLogConverter.INSTANCE.convert2Entity(logRecord);
        return CompletableFuture.completedFuture(save(operLogEntity));
    }
}